<template>
  <div class="ai-assistant-page" :class="{ 'sidebar-open': showSidebar }">
    <!-- 左侧侧边栏 -->
    <div class="sidebar" :class="{ 'sidebar-visible': showSidebar }">
      <div class="sidebar-header">
        <h3>AI助手</h3>
        <van-icon name="cross" size="20" @click="showSidebar = false" />
      </div>
      
      <!-- 助手列表 -->
      <div class="assistant-list">
        <div class="list-header">我的助手</div>
        <div 
          v-for="assistant in assistants" 
          :key="assistant.id"
          class="assistant-item"
          :class="{ 'active': currentAssistant?.id === assistant.id }"
          @click="switchAssistant(assistant)"
        >
          <div class="assistant-avatar-small">
            <van-icon name="user-circle-o" size="24" color="#9c27b0" />
          </div>
          <div class="assistant-info-small">
            <div class="assistant-name-small">{{ assistant.assistantName }}</div>
            <div class="assistant-role-small">{{ assistant.roleDesc.substring(0, 20) }}...</div>
          </div>
        </div>
        <div v-if="assistants.length === 0" class="empty-assistant">
          暂无助手
        </div>
      </div>

      <!-- 新建助手按钮 -->
      <div class="new-assistant-btn" @click="showCreateDialog = true">
        <van-icon name="plus" size="18" />
        <span>新建AI助手</span>
      </div>

      <!-- 会话记录列表 -->
      <div class="conversation-list">
        <div class="list-header">
          <span>会话记录</span>
          <van-icon 
            name="plus" 
            size="16" 
            class="add-conversation-icon"
            @click="createNewBlankConversation"
          />
        </div>
        <div 
          v-for="conversation in conversations" 
          :key="conversation.id"
          class="conversation-item"
          :class="{ 'active': currentConversationId === conversation.id }"
          @click="loadConversation(conversation.id)"
        >
          <div class="conversation-title">{{ conversation.title || '新会话' }}</div>
          <div class="conversation-time">{{ formatTime(conversation.updateTime) }}</div>
        </div>
        <div v-if="conversations.length === 0" class="empty-conversation">
          暂无会话记录
        </div>
      </div>
    </div>

    <!-- 遮罩层 -->
    <div class="sidebar-overlay" v-if="showSidebar" @click="showSidebar = false"></div>

    <!-- 主内容区 -->
    <div class="main-content">
      <!-- 顶部导航栏 -->
      <div class="top-bar" ref="topBarRef">
        <van-icon 
          name="bars" 
          size="20" 
          class="menu-icon" 
          @click="showSidebar = true"
        />
        <div class="assistant-title" v-if="currentAssistant">
          {{ currentAssistant.assistantName || currentAssistant.name }}
        </div>
        <div class="assistant-title" v-else>
          AI助手
        </div>
        <van-icon 
          name="arrow-left" 
          size="20" 
          class="back-icon" 
          @click="goToHome"
        />
      </div>

      <!-- 创建助手界面 -->
      <div v-if="!currentAssistant && assistants.length === 0" class="create-assistant-view">
        <div class="empty-state">
          <van-icon name="chat-o" size="64" color="#ccc" />
          <h3>还没有AI助手</h3>
          <p>创建一个AI助手开始对话吧</p>
          <van-button type="primary" size="large" @click="showCreateDialog = true">
            创建AI助手
          </van-button>
        </div>
      </div>

      <!-- 聊天界面 -->
      <div v-else class="chat-view">
        <!-- 消息列表 -->
        <div class="message-list" ref="messageListRef">
          <!-- 开场白提示（仅在没有任何消息时显示） -->
          <div v-if="currentMessages.length === 0 && currentAssistant?.greeting" class="greeting-container">
            <div class="greeting-card">
              <div class="greeting-text">{{ currentAssistant.greeting }}</div>
            </div>
          </div>
          
          <!-- 消息列表 -->
          <div 
            v-for="(msg, index) in currentMessages" 
            :key="index"
            class="message-item"
            :class="{ 'message-user': msg.role === 'user', 'message-assistant': msg.role === 'assistant' }"
          >
            <div class="message-content">
              <div class="message-text">
                <span v-if="msg.content">{{ msg.content }}</span>
                <span v-else-if="msg.loading" class="loading-placeholder">
                  <van-loading type="spinner" size="14" color="#999" />
                  <span class="loading-text">AI正在思考中...</span>
                </span>
              </div>
              <div class="message-time">{{ formatTime(msg.createTime) }}</div>
            </div>
          </div>
        </div>

        <!-- 输入框 -->
        <div class="input-area" ref="inputAreaRef">
          <div class="input-wrapper">
            <van-field
              v-model="inputMessage"
              type="textarea"
              rows="1"
              autosize
              :maxlength="2000"
              placeholder="输入消息..."
              class="message-input"
              @keyup.enter.exact="handleEnterKey"
              @input="handleInputChange"
            />
            <div class="input-actions">
              <van-icon 
                name="expand" 
                size="18" 
                class="expand-icon"
                @click="toggleFullInput"
              />
            </div>
          </div>
          <button 
            class="send-btn"
            @click="sendMessage"
            :disabled="!inputMessage.trim()"
            :class="{ 'send-btn-active': inputMessage.trim() }"
          >
            <van-icon name="arrow-up" size="14" />
          </button>
        </div>
      </div>
    </div>

    <!-- 全屏输入弹窗 -->
    <van-popup 
      v-model:show="showFullInput" 
      position="bottom" 
      round
      :style="{ height: '60%' }"
      :close-on-click-overlay="false"
    >
      <div class="full-input-dialog">
        <div class="full-input-header">
          <span>输入消息</span>
          <van-icon name="cross" size="20" @click="showFullInput = false" />
        </div>
        <div class="full-input-content">
          <van-field
            v-model="inputMessage"
            type="textarea"
            rows="10"
            autosize
            :maxlength="2000"
            placeholder="输入消息..."
            class="full-message-input"
          />
        </div>
        <div class="full-input-footer">
          <div class="char-count">{{ inputMessage.length }}/2000</div>
          <van-button 
            type="primary" 
            size="small" 
            @click="handleFullInputSend"
            :disabled="!inputMessage.trim()"
          >
            发送
          </van-button>
        </div>
      </div>
    </van-popup>

    <!-- 创建助手弹窗 -->
    <van-popup 
      v-model:show="showCreateDialog" 
      position="bottom" 
      round
      :style="{ height: '80%' }"
    >
      <div class="create-dialog">
        <div class="dialog-header">
          <h3>创建AI助手</h3>
          <van-icon name="cross" size="20" @click="showCreateDialog = false" />
        </div>
        <div class="dialog-content">
          <van-form @submit="createAssistant">
            <van-field
              v-model="formData.name"
              name="name"
              label="助手名称"
              placeholder="请输入助手名称"
              :rules="[{ required: true, message: '请输入助手名称' }]"
            />
            <van-field
              v-model="formData.role"
              name="role"
              label="角色信息"
              type="textarea"
              rows="3"
              placeholder="请输入角色信息，例如：你是一个专业的编程助手"
              :rules="[{ required: true, message: '请输入角色信息' }]"
            />
            <van-field
              v-model="formData.greeting"
              name="greeting"
              label="开场白"
              type="textarea"
              rows="2"
              placeholder="请输入开场白，例如：你好，我是你的AI助手"
              :rules="[{ required: true, message: '请输入开场白' }]"
            />
            <van-field
              name="uploader"
              label="上传文档"
            >
              <template #input>
                <div class="upload-wrapper">
                  <van-uploader
                    v-model="formData.files"
                    :max-count="5"
                    :after-read="afterRead"
                    :before-delete="beforeDelete"
                    accept=".pdf,.md"
                    :preview-image="false"
                    :preview-full-image="false"
                    multiple
                    :deletable="true"
                  >
                    <template #preview-cover="{ file }">
                      <div class="file-preview">
                        <div class="file-preview-row">
                          <!-- 文件图标 -->
                          <div class="file-icon-wrapper">
                            <van-icon :name="getFileIcon(file)" size="24" :color="getFileIconColor(file)" />
                          </div>
                          <!-- 文件信息 -->
                          <div class="file-info">
                            <div class="file-name-row">
                              <span class="file-name">{{ getOriginalFileName(file) }}</span>
                            </div>
                            <!-- 上传状态显示 -->
                            <div v-if="file.status === 'uploading'" class="upload-status">
                              <van-loading type="spinner" size="14" />
                              <span class="upload-text">上传中...</span>
                            </div>
                            <div v-else-if="file.status === 'failed'" class="upload-status error">
                              <van-icon name="close" size="14" color="#ee0a24" />
                              <span class="upload-text error-text">{{ file.message || '上传失败' }}</span>
                            </div>
                            <div v-else-if="file.status === 'done'" class="upload-status success">
                              <van-icon name="success" size="14" color="#07c160" />
                              <span class="upload-text success-text">上传成功</span>
                            </div>
                          </div>
                        </div>
                      </div>
                    </template>
                  </van-uploader>
                  <!-- 上传提示或文件列表 -->
                  <div v-if="formData.files.length === 0" class="upload-tip">
                    支持 PDF、MD 格式，最多上传 5 个文件
                  </div>
                  <div v-else class="uploaded-files-list">
                    <div class="uploaded-file-item" v-for="(file, index) in formData.files" :key="index">
                      <div class="file-item-content">
                        <van-icon :name="getFileIcon(file)" size="18" :color="getFileIconColor(file)" />
                        <span class="file-item-name">{{ getOriginalFileName(file) }}</span>
                      </div>
                      <van-icon 
                        v-if="file.status === 'done' && file.url"
                        name="eye-o" 
                        size="16" 
                        color="#1989fa" 
                        class="preview-icon"
                        @click="previewFile(file.url)"
                      />
                    </div>
                  </div>
                </div>
              </template>
            </van-field>
            <div class="dialog-footer">
              <van-button 
                round 
                block 
                type="primary" 
                native-type="submit"
                :loading="creating"
              >
                创建
              </van-button>
            </div>
          </van-form>
        </div>
      </div>
    </van-popup>

    <!-- 文档解析进度遮罩层 -->
    <van-overlay :show="showParseProgress" class="parse-progress-overlay">
      <div class="parse-progress-container">
        <div class="parse-progress-card">
          <div class="parse-progress-header">
            <h3>文档解析中</h3>
          </div>
          <div class="parse-progress-content">
            <!-- 圆形进度条 -->
            <div class="circular-progress-wrapper">
              <svg class="circular-progress" viewBox="0 0 100 100">
                <!-- 背景圆 -->
                <circle
                  class="progress-bg"
                  cx="50"
                  cy="50"
                  r="45"
                  fill="none"
                  stroke="#e5e5e5"
                  stroke-width="8"
                />
                <!-- 进度圆 -->
                <circle
                  class="progress-bar"
                  cx="50"
                  cy="50"
                  r="45"
                  fill="none"
                  stroke="#9c27b0"
                  stroke-width="8"
                  :stroke-dasharray="circumference"
                  :stroke-dashoffset="progressOffset"
                  stroke-linecap="round"
                  transform="rotate(-90 50 50)"
                />
              </svg>
              <div class="progress-text">
                <span class="progress-percent">{{ parseProgress }}%</span>
              </div>
            </div>
            <!-- 当前解析文档信息 -->
            <div class="parse-info">
              <div class="parse-status-text">
                <van-loading v-if="parseProgress < 100" type="spinner" size="16" color="#9c27b0" />
                <span class="status-text">{{ parseStatusText }}</span>
              </div>
              <div v-if="currentParseDoc" class="current-doc-info">
                <div class="doc-name">
                  <van-icon name="description" size="14" color="#666" />
                  <span>{{ currentParseDoc }}</span>
                </div>
                <div class="doc-progress">
                  文档 {{ currentDocIndex }}/{{ totalDocCount }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </van-overlay>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, computed, onUnmounted } from 'vue';
import { showToast, showConfirmDialog } from 'vant';
import { useRouter } from 'vue-router';
import { uploadBatchFiles as uploadBatchFilesAPI, deleteFileByUrl } from '../api/minioApi';
import { 
  createAssistant as createAssistantAPI, 
  getAssistantList,
  startDocumentParseTask as startDocumentParseTaskAPI,
  getDocumentParseStatus as getDocumentParseStatusAPI
} from '../api/aiApi';
import { userStore } from '../stores/user/user';
import { getToken } from '../request/request';

const router = useRouter();
const userStoreAPI = userStore();

// 侧边栏控制
const showSidebar = ref(false);

// 创建助手弹窗
const showCreateDialog = ref(false);
const creating = ref(false);

// 全屏输入
const showFullInput = ref(false);

// 文档解析进度相关
const showParseProgress = ref(false);
const parseProgress = ref(0);
const currentDocIndex = ref(0);
const totalDocCount = ref(0);
const currentParseDoc = ref('');
const parseStatusText = ref('准备解析文档...');
const parseTaskId = ref<string | null>(null);
const PARSE_STATUS_POLL_INTERVAL = 2000;
const PARSE_STATUS_MAX_DURATION = 10 * 60 * 1000;
let parseStatusPollingTimer: number | null = null;
let parseStatusPollingStartTime = 0;

// 文档解析进度相关计算属性
const circumference = 2 * Math.PI * 45; // 圆的周长
const progressOffset = computed(() => {
  return circumference - (parseProgress.value / 100) * circumference;
});

const clearParseStatusPolling = () => {
  if (parseStatusPollingTimer !== null) {
    clearTimeout(parseStatusPollingTimer);
    parseStatusPollingTimer = null;
  }
};

// 表单数据
const formData = ref({
  name: '',
  role: '',
  greeting: '',
  files: [] as any[]
});

// 助手列表
const assistants = ref<any[]>([]);
const currentAssistant = ref<any>(null);

// 会话列表
const conversations = ref<any[]>([]);
const currentConversationId = ref<number | null>(null);

// 当前消息列表
const currentMessages = ref<any[]>([]);
const inputMessage = ref('');
const messageListRef = ref<HTMLElement | null>(null);
const inputAreaRef = ref<HTMLElement | null>(null);
const topBarRef = ref<HTMLElement | null>(null);

// 初始化
onMounted(() => {
  loadAssistants();
  loadConversations();
});

onUnmounted(() => {
  clearParseStatusPolling();
});

// 加载助手列表
const loadAssistants = async () => {
  try {
    const res: any = await getAssistantList();
    if (res.code === 200 && res.data) {
      assistants.value = res.data;
      // 如果有助手且没有当前助手，选择第一个
      if (assistants.value.length > 0 && !currentAssistant.value) {
        currentAssistant.value = assistants.value[0];
        // 加载第一个助手的会话
        await loadConversations();
      }
    } else {
      assistants.value = [];
      console.error('获取助手列表失败:', res.message);
    }
  } catch (error: any) {
    console.error('加载助手列表错误:', error);
    assistants.value = [];
  }
};

// 切换助手
const switchAssistant = async (assistant: any) => {
  // 保存当前会话
  if (currentAssistant.value && currentConversationId.value) {
    saveConversation();
  }
  
  // 切换助手
  currentAssistant.value = assistant;
  currentConversationId.value = null;
  currentMessages.value = [];
  
  // 加载新助手的会话
  await loadConversations();
  
  // 如果有会话，加载第一个；否则创建新会话
  if (conversations.value.length > 0) {
    loadConversation(conversations.value[0].id);
  } else {
    await createNewConversation();
  }
  
  showSidebar.value = false;
};

// 加载会话列表
const loadConversations = async () => {
  // TODO: 从后端加载会话列表
  const stored = localStorage.getItem(`ai_conversations_${currentAssistant.value?.id}`);
  if (stored) {
    conversations.value = JSON.parse(stored);
  } else {
    conversations.value = [];
  }
};

// 创建助手
const createAssistant = async () => {
  if (!formData.value.name || !formData.value.role || !formData.value.greeting) {
    showToast('请填写完整信息');
    return;
  }

  creating.value = true;
  try {
    // 构建文档列表，只包含上传成功的文件
    const docList = formData.value.files
      .filter((f: any) => f.status === 'done' && f.url && f.originalFileName)
      .map((f: any) => {
        // 获取文件扩展名作为文档类型
        const fileName = f.originalFileName || '';
        const lastDot = fileName.lastIndexOf('.');
        const docType = lastDot > -1 ? fileName.substring(lastDot + 1).toLowerCase() : '';
        
        // 获取文件大小（MB），如果文件对象存在则使用，否则设为0
        const fileSize = f.file ? (f.file.size / (1024 * 1024)) : 0;
        
        return {
          docUrl: f.url,
          docName: f.originalFileName,
          docType: docType,
          docSize: parseFloat(fileSize.toFixed(2)) // 保留两位小数
        };
      });
    
    // 构建请求参数，匹配后端接口
    const requestData = {
      assistantName: formData.value.name,
      roleDesc: formData.value.role,
      greeting: formData.value.greeting,
      docList: docList
    };
    
    // 调用后端API创建助手
    const res: any = await createAssistantAPI(requestData);
    
    if (res.code === 200 && res.data) {
      const newAssistant = res.data;

      showCreateDialog.value = false;

      // 如果有文档，需要解析文档
      if (docList.length > 0) {
        try {
          await startDocumentParsingWorkflow(newAssistant.id, docList);
          showToast('文档解析完成');
        } catch (error: any) {
          console.error('文档解析错误:', error);
          showToast(error?.message || '文档解析失败');
        }
      }

      // 重新加载助手列表（从后端获取最新数据）
      await loadAssistants();
      // 切换到新创建的助手
      await switchAssistant(newAssistant);
      
      // 重置表单
      formData.value = {
        name: '',
        role: '',
        greeting: '',
        files: []
      };
      
      if (docList.length === 0) {
        showToast('创建成功');
      }
    } else {
      showToast(res.message || '创建失败');
    }
  } catch (error: any) {
    console.error('创建助手错误:', error);
    showToast(error.message || '创建失败，请稍后重试');
  } finally {
    creating.value = false;
  }
};

// 创建新会话
const createNewConversation = async () => {
  const newConversation = {
    id: Date.now(),
    assistantId: currentAssistant.value.id,
    title: '新会话',
    messages: [] as any[],
    createTime: Date.now(),
    updateTime: Date.now()
  };

  conversations.value.unshift(newConversation);
  localStorage.setItem(`ai_conversations_${currentAssistant.value.id}`, JSON.stringify(conversations.value));

  currentConversationId.value = newConversation.id;
  currentMessages.value = [];
  // 开场白不再添加到消息列表，而是在UI中单独显示
};

// 创建新的空白会话
const createNewBlankConversation = async () => {
  if (!currentAssistant.value) {
    showToast('请先选择AI助手');
    return;
  }

  const newConversation = {
    id: Date.now(),
    assistantId: currentAssistant.value.id,
    title: '新会话',
    messages: [] as any[],
    createTime: Date.now(),
    updateTime: Date.now()
  };

  conversations.value.unshift(newConversation);
  localStorage.setItem(`ai_conversations_${currentAssistant.value.id}`, JSON.stringify(conversations.value));

  // 切换到新创建的会话
  currentConversationId.value = newConversation.id;
  currentMessages.value = [];
  
  // 关闭侧边栏
  showSidebar.value = false;
  
  showToast('已创建新会话');
};

// 加载会话
const loadConversation = (conversationId: number) => {
  const conversation = conversations.value.find(c => c.id === conversationId);
  if (conversation) {
    currentConversationId.value = conversationId;
    currentMessages.value = conversation.messages || [];
    showSidebar.value = false;
    scrollToBottom();
  }
};

// 处理回车键
const handleEnterKey = (e: KeyboardEvent) => {
  // Shift+Enter 换行，Enter 发送
  if (!e.shiftKey) {
    e.preventDefault();
    sendMessage();
  }
};

// 全屏输入发送
const handleFullInputSend = () => {
  showFullInput.value = false;
  sendMessage();
};

// 切换全屏输入
const toggleFullInput = () => {
  showFullInput.value = true;
};

// 处理输入变化
const handleInputChange = () => {
  // 不再隐藏顶部栏，保持顶部栏始终显示
  // 输入框高度变化时不需要调整顶部栏
};

// 发送消息 - 使用 SSE 流式输出
const sendMessage = async () => {
  if (!inputMessage.value.trim()) {
    return;
  }

  if (!currentAssistant.value) {
    showToast('请先创建AI助手');
    return;
  }

  // 获取当前用户ID
  const currentUser: any = await userStoreAPI.getCurrentUser();
  if (!currentUser || !currentUser.id) {
    showToast('请先登录');
    return;
  }

  // 如果没有当前会话，创建新会话
  if (!currentConversationId.value) {
    await createNewConversation();
  }

  // 添加用户消息到列表
  const userMessage = {
    role: 'user',
    content: inputMessage.value,
    createTime: Date.now()
  };

  currentMessages.value.push(userMessage);
  const messageText = inputMessage.value;
  inputMessage.value = '';
  
  scrollToBottom();

  // 创建 AI 助手消息占位符，用于流式更新
  const assistantMessage = {
    role: 'assistant',
    content: '',
    loading: true, // 添加 loading 状态
    createTime: Date.now()
  };
  currentMessages.value.push(assistantMessage);
  // 获取消息在数组中的索引，用于后续更新
  const assistantMessageIndex = currentMessages.value.length - 1;
  scrollToBottom();

  // 构建 message JSON 字符串（后端会解析）
  const messageJson = JSON.stringify({
    msg_type: 1, // 1: 文本消息
    text: messageText
  });

  // 使用原生 EventSource 进行 SSE 流式调用（GET 请求）
  try {
    await streamChatWithFetch(
      messageJson,
      String(currentConversationId.value),
      currentAssistant.value.id,
      assistantMessageIndex
    );
  } catch (error: any) {
    console.error('AI聊天错误:', error);
    // 直接更新数组中的消息对象，确保响应式更新
    if (currentMessages.value[assistantMessageIndex]) {
      currentMessages.value[assistantMessageIndex].loading = false;
      currentMessages.value[assistantMessageIndex].content = error.message || 'AI回复失败，请稍后重试';
    }
    showToast(error.message || '网络错误，请稍后重试');
  }
};

// SSE 流式聊天处理 - 使用 Fetch API (支持自定义 header)
const streamChatWithFetch = async (
    message: string,
    sessionId: string,
    assistantId: number,
    assistantMessageIndex: number
) => {
  const token = getToken();
  if (!token) {
    showToast('请先登录');
    return;
  }

  // 使用与 request.ts 相同的 baseURL
  const baseURL = 'http://localhost:8080/partner';

  // 构建 GET 请求 URL，参数通过 URL 参数传递
  const params = new URLSearchParams({
    message: message,
    sessionId: sessionId,
    assistantId: String(assistantId)
  });

  const url = `${baseURL}/ai/chat/sse_emitter?${params.toString()}`;

  return new Promise<void>(async (resolve, reject) => {
    const abortController = new AbortController();
    const signal = abortController.signal;

    // 设置超时（30秒）
    const timeoutId = setTimeout(() => {
      abortController.abort();
      reject(new Error('请求超时'));
    }, 30000);

    try {
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'text/plain; charset=utf-8',
          'Accept': 'text/event-stream',
        },
        signal: signal,
      });

      clearTimeout(timeoutId);

       if (!response.ok) {
         const errorText = await response.text();
         let errorMessage = `HTTP ${response.status}`;
         try {
           const errorData = JSON.parse(errorText);
           errorMessage = errorData.message || errorData.data || errorText;
         } catch (e) {
           errorMessage = errorText || `HTTP ${response.status}`;
         }
         // 更新数组中的消息对象
         const currentMessage = currentMessages.value[assistantMessageIndex];
         if (currentMessage) {
           currentMessage.content = errorMessage;
           currentMessage.loading = false;
         }
         throw new Error(errorMessage);
       }

      if (!response.body) {
        throw new Error('响应体不可读');
      }

       const reader = response.body.getReader();
       const decoder = new TextDecoder();
       let hasReceivedData = false;

       try {
         while (true) {
           const {done, value} = await reader.read();
           if (done) {
             break;
           }

           // 解码数据并添加到缓冲区
           const chunk = decoder.decode(value, {stream: true});
           console.log('chunk:', chunk)

           // SSE 格式：
           // 每个事件块可能包含：
           // event:complete\ndata:AI回复完成
           // data:欢迎随时向我提问。
           // event:error\ndata:AI回复异常
           const events = chunk.split('\n');
           console.log('events:', events)

           // 获取当前消息对象，确保响应式更新
           const currentMessage = currentMessages.value[assistantMessageIndex];
           if (!currentMessage) {
             await reader.cancel();
             reject(new Error('消息对象不存在'));
             return;
           }

           if (events.length > 1 && (events[0] == 'event:complete' || events[0] == 'event:error')) {
             // 处理完成或错误事件
             currentMessage.loading = false;
             const eventData = events[1].substring(5).trim();
             currentMessage.content += eventData;
             
             // 强制触发响应式更新
             await nextTick();
             saveConversation();
             scrollToBottom();
             await reader.cancel();
             
             if (events[0] == 'event:error') {
               reject(new Error(eventData || 'AI回复异常'));
             } else {
               resolve();
             }
             return;
           } else {
             // 处理普通数据流
             hasReceivedData = true;
             const data = events[0].substring(5).trim();
             
             // 收到第一个数据时停止 loading
             if (currentMessage.loading) {
               currentMessage.loading = false;
             }
             
             // 直接更新数组中的消息对象，确保响应式更新
             currentMessage.content += data;
             
             // 强制触发响应式更新和 DOM 更新
             await nextTick();
             scrollToBottom();
           }
         }

         // 流自然结束
         const currentMessage = currentMessages.value[assistantMessageIndex];
         if (currentMessage) {
           currentMessage.loading = false;
           await nextTick();
         }
         if (hasReceivedData) {
           saveConversation();
         }
         scrollToBottom();
         resolve();

      } catch (readError: any) {
        if (readError.name === 'AbortError') {
          reject(new Error('请求被中止'));
        } else {
          reject(readError);
        }
      } finally {
        reader.releaseLock();
      }

    } catch (error: any) {
      clearTimeout(timeoutId);
      // 更新数组中的消息对象
      const currentMessage = currentMessages.value[assistantMessageIndex];
      if (currentMessage) {
        currentMessage.loading = false;
      }

      if (error.name === 'AbortError') {
        reject(new Error('请求超时或被中止'));
      } else {
        reject(error);
      }
    }
  });
};

// 保存会话
const saveConversation = () => {
  if (!currentConversationId.value) return;

  const conversation = conversations.value.find(c => c.id === currentConversationId.value);
  if (conversation) {
    conversation.messages = currentMessages.value;
    conversation.updateTime = Date.now();
    // 更新标题（使用第一条用户消息）
    const firstUserMsg = currentMessages.value.find(m => m.role === 'user');
    if (firstUserMsg) {
      conversation.title = firstUserMsg.content.substring(0, 20);
    }
    localStorage.setItem(`ai_conversations_${currentAssistant.value.id}`, JSON.stringify(conversations.value));
  }
};

// 文件上传后处理 - 支持单文件和多文件上传
const afterRead = async (file: any | any[]) => {
  // 如果是数组，说明是多文件上传，使用批量上传接口
  if (Array.isArray(file) && file.length > 0) {
    await handleBatchUpload(file);
    return;
  }
  
  // 单文件上传，也使用批量上传接口（兼容性处理）
  if (file && file.file) {
    await handleBatchUpload([file]);
  }
};

// 批量上传文件处理
const handleBatchUpload = async (files: any[]) => {
  // 过滤出有效的文件
  const validFiles = files.filter(f => f && f.file);
  
  if (validFiles.length === 0) {
    showToast('没有可上传的文件');
    return;
  }

  // 设置所有文件为上传中状态 - 立即更新状态
  validFiles.forEach((f) => {
    f.status = 'uploading';
    f.message = '上传中...';
    f.percentage = 0;
  });
  
  // 强制触发响应式更新
  formData.value.files = [...formData.value.files];
  await nextTick();

  try {
    // 提取 File 对象
    const fileObjects = validFiles.map(f => f.file);
    
    // 调用批量上传接口
    const res: any = await uploadBatchFilesAPI(fileObjects);
    
    if (res.code === 200 && res.data) {
      const successList = res.data; // FileUploadResponse[]
      
      // 创建成功上传文件的映射（使用原始文件名作为key）
      const successMap = new Map();
      successList.forEach((item: any) => {
        successMap.set(item.originalFileName, item);
      });
      
      // 更新文件状态 - 遍历 formData.files 更新
      formData.value.files.forEach((f: any) => {
        if (!f.file) return;
        
        const originalFileName = f.file.name;
        const successItem = successMap.get(originalFileName);
        
        if (successItem) {
          // 上传成功 - 只保存 url 和 originalFileName
          f.url = successItem.url;
          f.originalFileName = successItem.originalFileName;
          f.status = 'done';
        } else if (f.status === 'uploading') {
          // 上传失败（不在成功列表中）
          f.status = 'failed';
          f.message = '上传失败';
          f.percentage = 0;
        }
      });
      
      // 强制触发响应式更新
      formData.value.files = [...formData.value.files];
      await nextTick();
      
      // 显示上传结果
      const successCount = successList.length;
      const failCount = validFiles.length - successCount;
      
      if (failCount === 0) {
        showToast(`成功上传 ${successCount} 个文件`);
        console.log('formData.value.files:', formData.value.files)
      } else {
        showToast(`成功上传 ${successCount} 个，失败 ${failCount} 个`);
      }
    } else {
      // 批量上传失败
      formData.value.files.forEach((f: any) => {
        if (f.status === 'uploading') {
          f.status = 'failed';
          f.message = res.message || '上传失败';
          f.percentage = 0;
        }
      });
      formData.value.files = [...formData.value.files];
      await nextTick();
      showToast(res.message || '文件上传失败');
    }
  } catch (error: any) {
    // 上传异常
    formData.value.files.forEach((f: any) => {
      if (f.status === 'uploading') {
        f.status = 'failed';
        f.message = '上传失败';
        f.percentage = 0;
      }
    });
    formData.value.files = [...formData.value.files];
    await nextTick();
    console.error('批量文件上传错误:', error);
    showToast('文件上传失败，请稍后重试');
  }
};

// 文件删除前处理
const beforeDelete = async (file: any) => {
  try {
    await showConfirmDialog({
      title: '确认删除',
      message: '确定要删除这个文件吗？'
    });
    
    // 如果文件已上传到服务器，调用删除接口
    if (file.url && file.status === 'done') {
      try {
        const res: any = await deleteFileByUrl(file.url);
        if (res.code === 200) {
          showToast('文件删除成功');
          return true;
        } else {
          showToast(res.message || '文件删除失败');
          return false;
        }
      } catch (error) {
        console.error('删除文件错误:', error);
        showToast('文件删除失败');
        return false;
      }
    }
    
    // 如果文件还未上传或上传失败，直接允许删除
    return true;
  } catch {
    // 用户取消删除
    return false;
  }
};

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (messageListRef.value) {
      messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
    }
  });
};

// 格式化时间
const formatTime = (timestamp: number) => {
  const date = new Date(timestamp);
  const now = new Date();
  const diff = now.getTime() - date.getTime();
  const minutes = Math.floor(diff / 60000);
  const hours = Math.floor(diff / 3600000);
  const days = Math.floor(diff / 86400000);

  if (minutes < 1) return '刚刚';
  if (minutes < 60) return `${minutes}分钟前`;
  if (hours < 24) return `${hours}小时前`;
  if (days < 7) return `${days}天前`;
  
  return date.toLocaleDateString();
};

// 返回首页
const goToHome = () => {
  router.push('/index');
};

// 获取原始文件名（优先使用 originalFileName）
const getOriginalFileName = (file: any) => {
  // 优先使用服务器返回的原始文件名
  if (file.originalFileName) {
    return file.originalFileName;
  }
  // 其次使用文件对象的名称
  if (file.file && file.file.name) {
    return file.file.name;
  }
  // 最后使用 name 属性
  if (file.name) {
    return file.name;
  }
  // 从URL中提取文件名
  if (file.url) {
    const urlParts = file.url.split('/');
    const fileName = urlParts[urlParts.length - 1];
    return fileName.split('?')[0];
  }
  return '未知文件';
};

// 获取文件扩展名
const getFileExtension = (file: any) => {
  const fileName = getOriginalFileName(file);
  const lastDot = fileName.lastIndexOf('.');
  if (lastDot === -1) return '';
  return fileName.substring(lastDot + 1).toLowerCase();
};

// 获取文件图标
const getFileIcon = (file: any) => {
  const ext = getFileExtension(file);
  switch (ext) {
    case 'pdf':
      return 'description'; // PDF 图标
    case 'md':
    case 'markdown':
      return 'edit'; // Markdown 图标
    default:
      return 'description'; // 默认文档图标
  }
};

// 获取文件图标颜色
const getFileIconColor = (file: any) => {
  const ext = getFileExtension(file);
  switch (ext) {
    case 'pdf':
      return '#dc3545'; // PDF 红色
    case 'md':
    case 'markdown':
      return '#1989fa'; // Markdown 蓝色
    default:
      return '#1989fa'; // 默认蓝色
  }
};

// 预览文件
const previewFile = (url: string) => {
  if (url) {
    window.open(url, '_blank');
  }
};

// 启动文档解析任务并轮询状态
const startDocumentParsingWorkflow = async (assistantId: number, docList: any[]) => {
  if (!assistantId || docList.length === 0) {
    return;
  }

  const validDocs = docList.filter(doc => !!doc.docUrl);
  const requestPayload = validDocs.map(doc => ({
    docUrl: doc.docUrl,
    docName: doc.docName || '未命名文档',
    docType: doc.docType || ''
  }));

  if (requestPayload.length === 0) {
    throw new Error('没有可解析的文档');
  }

  showParseProgress.value = true;
  parseProgress.value = 0;
  currentDocIndex.value = 0;
  currentParseDoc.value = '';
  totalDocCount.value = requestPayload.length;
  parseStatusText.value = '准备解析文档...';
  parseTaskId.value = null;
  parseStatusPollingStartTime = Date.now();
  clearParseStatusPolling();

  try {
      const parseRes: any = await startDocumentParseTaskAPI(assistantId, requestPayload);
    if (parseRes.code !== 200 || !parseRes.data?.taskId) {
      throw new Error(parseRes.message || '解析任务创建失败');
    }

    parseTaskId.value = parseRes.data.taskId;
    if (!parseTaskId.value) {
      throw new Error('解析任务ID无效');
    }
    await pollDocumentParseStatus(parseTaskId.value, requestPayload.length);
  } finally {
    clearParseStatusPolling();
    parseTaskId.value = null;
    setTimeout(() => {
      showParseProgress.value = false;
    }, 800);
  }
};

const pollDocumentParseStatus = (taskId: string, expectedTotal: number) => {
  let consecutiveErrors = 0;
  parseStatusPollingStartTime = Date.now();

  return new Promise<void>((resolve, reject) => {
    const poll = async () => {
      if (Date.now() - parseStatusPollingStartTime > PARSE_STATUS_MAX_DURATION) {
        clearParseStatusPolling();
        parseStatusText.value = '解析超时，请稍后重试';
        reject(new Error('解析超时，请稍后重试'));
        return;
      }

      try {
        const statusRes: any = await getDocumentParseStatusAPI(taskId);
        if (statusRes.code !== 200 || !statusRes.data) {
          throw new Error(statusRes.message || '获取解析状态失败');
        }

        consecutiveErrors = 0;
        updateParseProgressState(statusRes.data, expectedTotal);

        const statusValue = (statusRes.data.status || statusRes.data.taskStatus || '').toString().toUpperCase();
        if (['SUCCESS', 'COMPLETED', 'FINISHED'].includes(statusValue)) {
          clearParseStatusPolling();
          resolve();
          return;
        }

        if (['FAILED', 'ERROR'].includes(statusValue)) {
          const failureMessage = statusRes.data.errorMessage || statusRes.data.statusMessage || '文档解析失败';
          parseStatusText.value = failureMessage;
          clearParseStatusPolling();
          reject(new Error(failureMessage));
          return;
        }

        if (parseProgress.value >= 100 || (totalDocCount.value > 0 && currentDocIndex.value >= totalDocCount.value)) {
          parseStatusText.value = statusRes.data.statusMessage || '解析完成';
          clearParseStatusPolling();
          resolve();
          return;
        }
      } catch (error: any) {
        consecutiveErrors += 1;
        if (consecutiveErrors >= 3) {
          const message = error?.message || '获取解析状态失败';
          parseStatusText.value = message;
          clearParseStatusPolling();
          reject(error instanceof Error ? error : new Error(message));
          return;
        }
        parseStatusText.value = '获取解析状态异常，正在重试...';
      }

      clearParseStatusPolling();
      parseStatusPollingTimer = window.setTimeout(poll, PARSE_STATUS_POLL_INTERVAL);
    };

    poll();
  });
};

const updateParseProgressState = (statusData: any, fallbackTotal: number) => {
  const progressValue = typeof statusData.progress === 'number'
    ? statusData.progress
    : typeof statusData.overallProgress === 'number'
      ? statusData.overallProgress
      : parseProgress.value;
  parseProgress.value = Math.min(100, Math.max(0, Math.round(progressValue)));

  const total = statusData.totalCount ?? statusData.totalDocs ?? fallbackTotal ?? totalDocCount.value;
  if (typeof total === 'number' && total > 0) {
    totalDocCount.value = total;
  }

  const currentIndexValue = statusData.currentIndex ?? statusData.currentDocIndex ?? statusData.completedCount;
  if (typeof currentIndexValue === 'number') {
    currentDocIndex.value = currentIndexValue;
  }

  if (statusData.currentDocName || statusData.docName) {
    currentParseDoc.value = statusData.currentDocName || statusData.docName;
  }

  if (statusData.statusMessage || statusData.message || statusData.status) {
    parseStatusText.value = statusData.statusMessage || statusData.message || statusData.status;
  }
};
</script>

<style scoped>
.ai-assistant-page {
  display: flex;
  height: 100vh;
  background-color: #f7f8fa;
  position: relative;
  overflow: hidden;
}

/* 侧边栏 */
.sidebar {
  position: fixed;
  left: -280px;
  top: 0;
  width: 280px;
  height: 100vh;
  background-color: #fff;
  z-index: 1001;
  transition: left 0.3s ease;
  display: flex;
  flex-direction: column;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
}

.sidebar-visible {
  left: 0;
}

.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.sidebar-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}

.current-assistant {
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.assistant-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.assistant-avatar {
  flex-shrink: 0;
}

.assistant-details {
  flex: 1;
  min-width: 0;
}

.assistant-name {
  font-size: 16px;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assistant-role {
  font-size: 12px;
  color: #999;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.new-assistant-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  margin: 8px 16px;
  background-color: #9c27b0;
  color: #fff;
  border-radius: 8px;
  cursor: pointer;
  font-size: 14px;
}

.new-assistant-btn:active {
  opacity: 0.8;
}

.conversation-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}

.list-header {
  padding: 8px 16px;
  font-size: 12px;
  color: #999;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.add-conversation-icon {
  cursor: pointer;
  color: #9c27b0;
  padding: 4px;
  border-radius: 4px;
  transition: all 0.2s;
}

.add-conversation-icon:hover {
  background-color: #f0e6f5;
  transform: scale(1.1);
}

.add-conversation-icon:active {
  transform: scale(0.95);
}

.conversation-item {
  padding: 12px 16px;
  cursor: pointer;
  border-left: 3px solid transparent;
  transition: background-color 0.2s;
}

.conversation-item:hover {
  background-color: #f5f5f5;
}

.conversation-item.active {
  background-color: #f0e6f5;
  border-left-color: #9c27b0;
}

.conversation-title {
  font-size: 14px;
  color: #333;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversation-time {
  font-size: 12px;
  color: #999;
}

.empty-conversation {
  padding: 32px 16px;
  text-align: center;
  color: #999;
  font-size: 14px;
}

/* 助手列表 */
.assistant-list {
  border-bottom: 1px solid #eee;
  padding: 8px 0;
  max-height: 200px;
  overflow-y: auto;
}

.assistant-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  border-left: 3px solid transparent;
  transition: background-color 0.2s;
}

.assistant-item:hover {
  background-color: #f5f5f5;
}

.assistant-item.active {
  background-color: #f0e6f5;
  border-left-color: #9c27b0;
}

.assistant-avatar-small {
  flex-shrink: 0;
}

.assistant-info-small {
  flex: 1;
  min-width: 0;
}

.assistant-name-small {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.assistant-role-small {
  font-size: 12px;
  color: #999;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.empty-assistant {
  padding: 16px;
  text-align: center;
  color: #999;
  font-size: 14px;
}

/* 遮罩层 */
.sidebar-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

/* 主内容区 */
.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  transition: margin-left 0.3s ease;
  margin-left: 0;
}

.sidebar-open .main-content {
  margin-left: 280px;
}

.top-bar {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background-color: #fff;
  border-bottom: 1px solid #eee;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  transition: transform 0.3s ease;
}

.top-bar-hidden {
  transform: translateY(-100%);
}

.menu-icon {
  margin-right: 12px;
  cursor: pointer;
  color: #333;
}

.assistant-title {
  font-size: 18px;
  font-weight: 600;
  color: #333;
  flex: 1;
  text-align: center;
}

.back-icon {
  cursor: pointer;
  color: #333;
  margin-left: auto;
}

.back-icon:active {
  opacity: 0.6;
}

/* 创建助手视图 */
.create-assistant-view {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty-state {
  text-align: center;
  padding: 32px;
}

.empty-state h3 {
  margin: 16px 0 8px;
  color: #333;
  font-size: 20px;
}

.empty-state p {
  margin: 0 0 24px;
  color: #999;
  font-size: 14px;
}

/* 聊天视图 */
.chat-view {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-top: 50px;
  padding-bottom: 80px;
  background-color: #f7f8fa;
  min-height: 0;
}

.message-list {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  padding-bottom: 16px;
  background-color: #f7f8fa;
  position: relative;
  display: flex;
  flex-direction: column;
}

.message-list:has(.greeting-container) {
  justify-content: flex-start;
}

.message-list:not(:has(.greeting-container)) {
  justify-content: flex-start;
}

/* 开场白容器 */
.greeting-container {
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1;
  pointer-events: none;
}

.greeting-card {
  min-width: 60vw;
  background: #fff;
  border-radius: 12px;
  padding: 20px 24px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  position: relative;
}

.greeting-text {
  font-size: 15px;
  line-height: 1.6;
  color: #333;
  word-wrap: break-word;
  word-break: break-word;
  white-space: pre-wrap;
  text-align: center;
  font-weight: 400;
  margin: 0;
}

.message-item {
  display: flex;
  margin-bottom: 16px;
  align-items: flex-start;
}

.message-user {
  justify-content: flex-end;
}

.message-assistant {
  justify-content: flex-start;
}

.message-content {
  max-width: 70%;
  min-width: 0;
  width: fit-content;
}

.message-user .message-content {
  text-align: left;
}

.message-assistant .message-content {
  text-align: left;
}

.message-text {
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.5;
  word-wrap: break-word;
  word-break: break-word;
  white-space: pre-wrap;
  display: inline-block;
  width: fit-content;
  max-width: 100%;
}

.loading-placeholder {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #999;
}

.loading-text {
  font-size: 14px;
}

.message-user .message-text {
  text-align: left;
}

.message-assistant .message-text {
  background-color: #fff;
  color: #333;
  border: 1px solid #eee;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}

.message-user .message-text {
  background-color: #9c27b0;
  color: #fff;
  box-shadow: 0 1px 2px rgba(156, 39, 176, 0.2);
}

.message-time {
  font-size: 11px;
  color: #999;
  margin-top: 4px;
  padding: 0 4px;
}

.input-area {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 8px 16px 16px;
  background-color: transparent;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 99;
  transition: transform 0.3s ease;
}

.input-wrapper {
  flex: 1;
  position: relative;
  background-color: #fff;
  border-radius: 24px;
  padding: 8px 12px;
  min-height: 44px;
  display: flex;
  align-items: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.message-input {
  flex: 1;
  border: none;
  background: transparent;
  resize: none;
  max-height: 120px;
  overflow-y: auto;
}

.message-input :deep(.van-field__control) {
  border: none;
  background: transparent;
  padding: 0;
  font-size: 14px;
  line-height: 1.5;
}

.input-actions {
  display: flex;
  align-items: center;
  margin-left: 8px;
}

.expand-icon {
  color: #999;
  cursor: pointer;
  padding: 4px;
}

.expand-icon:active {
  opacity: 0.6;
}

.send-btn {
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  max-width: 44px;
  max-height: 44px;
  border-radius: 50%;
  border: none;
  padding: 0;
  margin: 0;
  background-color: #e0e0e0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  box-sizing: border-box;
  overflow: hidden;
}

.send-btn:disabled {
  cursor: not-allowed;
}

.send-btn-active {
  background-color: #64b5f6;
  color: #fff;
  transform: scale(1);
}

.send-btn-active:active {
  transform: scale(0.95);
}

/* 全屏输入弹窗 */
.full-input-dialog {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.full-input-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
  font-size: 16px;
  font-weight: 600;
}

.full-input-content {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
}

.full-message-input {
  width: 100%;
  min-height: 200px;
}

.full-message-input :deep(.van-field__control) {
  min-height: 200px;
  font-size: 14px;
  line-height: 1.6;
}

.full-input-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  border-top: 1px solid #eee;
}

.char-count {
  font-size: 12px;
  color: #999;
}

/* 创建弹窗 */
.create-dialog {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.dialog-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}

.dialog-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}

.dialog-footer {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #eee;
}

/* 上传区域包装器 */
.upload-wrapper {
  width: 100%;
}

.upload-tip {
  font-size: 12px;
  color: #969799;
  margin-top: 8px;
  line-height: 1.5;
}

/* 已上传文件列表 */
.uploaded-files-list {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #eee;
}

.uploaded-file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #f5f5f5;
}

.uploaded-file-item:last-child {
  border-bottom: none;
}

.file-item-content {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}

.file-item-name {
  font-size: 14px;
  color: #323233;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.preview-icon {
  cursor: pointer;
  padding: 4px;
  flex-shrink: 0;
  transition: opacity 0.2s;
}

.preview-icon:active {
  opacity: 0.6;
}

/* 文档上传样式 */
:deep(.van-uploader__upload) {
  background-color: #f7f8fa;
  border: 1px dashed #dcdee0;
  border-radius: 8px;
  position: relative;
}

/* 隐藏默认的相机图标 */
:deep(.van-uploader__upload-icon) {
  display: none !important;
}

/* 使用伪元素显示文档图标 */
:deep(.van-uploader__upload)::before {
  content: '';
  display: block;
  width: 32px;
  height: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23969799'%3E%3Cpath d='M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  margin: 0 auto 8px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin-top: -12px;
}

:deep(.van-uploader__upload-text) {
  font-size: 12px;
  color: #969799;
  margin-top: 24px;
  position: relative;
  z-index: 1;
}

:deep(.van-uploader__preview) {
  margin: 0 0 8px 0;
  width: 100%;
}

/* 隐藏图片预览，显示文档预览 */
:deep(.van-uploader__preview-image) {
  display: none !important;
}

:deep(.van-uploader__preview-delete) {
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  top: 4px;
  right: 4px;
}

/* 文件预览容器 - 一行一个 */
.file-preview {
  display: flex;
  width: 100%;
  min-height: 60px;
  padding: 12px;
  background-color: #f7f8fa;
  border-radius: 8px;
  position: relative;
  box-sizing: border-box;
}

/* 文件预览行 - 横向布局 */
.file-preview-row {
  display: flex;
  align-items: center;
  width: 100%;
  gap: 12px;
}

/* 文件图标容器 */
.file-icon-wrapper {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
}

/* 文件信息容器 */
.file-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* 文件名行 */
.file-name-row {
  display: flex;
  align-items: center;
  width: 100%;
}

.file-name {
  font-size: 14px;
  color: #323233;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
  line-height: 1.5;
}

.upload-status {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  margin-top: 2px;
  justify-content: flex-start;
}

.upload-text {
  color: #969799;
  font-size: 11px;
}

.upload-status.success .upload-text {
  color: #07c160;
}

.upload-status.error .upload-text {
  color: #ee0a24;
}

/* 上传中的文件样式 */
:deep(.van-uploader__preview) {
  margin: 0 8px 8px 0;
}

:deep(.van-uploader__preview[data-status="uploading"]) {
  opacity: 0.8;
}

:deep(.van-uploader__preview[data-status="failed"]) {
  border: 1px solid #ee0a24;
}

:deep(.van-uploader__preview[data-status="done"]) {
  border: 1px solid #07c160;
}

/* 文档解析进度遮罩层 */
.parse-progress-overlay {
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}

.parse-progress-container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.parse-progress-card {
  background: #fff;
  border-radius: 16px;
  padding: 32px;
  min-width: 320px;
  max-width: 90%;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.parse-progress-header {
  text-align: center;
  margin-bottom: 24px;
}

.parse-progress-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #333;
}

.parse-progress-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
}

/* 圆形进度条 */
.circular-progress-wrapper {
  position: relative;
  width: 120px;
  height: 120px;
}

.circular-progress {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.progress-bg {
  transition: stroke-dashoffset 0.3s ease;
}

.progress-bar {
  transition: stroke-dashoffset 0.3s ease;
}

.progress-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.progress-percent {
  font-size: 24px;
  font-weight: 600;
  color: #9c27b0;
}

/* 解析信息 */
.parse-info {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.parse-status-text {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #666;
}

.status-text {
  font-size: 14px;
  color: #666;
}

.current-doc-info {
  width: 100%;
  padding: 12px;
  background: #f7f8fa;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.doc-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #333;
  font-weight: 500;
}

.doc-name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.doc-progress {
  font-size: 12px;
  color: #999;
  text-align: center;
}

/* 响应式 */
@media (max-width: 768px) {
  .sidebar-open .main-content {
    margin-left: 0;
  }
  
  .message-content {
    max-width: 85%;
  }
  
  .input-area {
    padding: 8px 10px;
  }
  
  .send-btn {
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
    max-width: 40px;
    max-height: 40px;
  }
  
  .input-wrapper {
    min-height: 40px;
    border-radius: 20px;
  }
}
</style>

